package com.joven.shelltest.utils.desensitized;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.joven.shelltest.annotation.SensitiveSimple;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.Collections;

/**
 * @author wzj
 * @since 2024/11/5 9:20
 */
public class SensitiveSimpleSerializer extends JsonSerializer<String> implements ContextualSerializer {

    private SensitiveSimple sensitiveSimple;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        String val = value;
        if (sensitiveSimple != null && StringUtils.hasLength(val)) {
            String m = sensitiveSimple.mask();
            int start = sensitiveSimple.start();
            int end = sensitiveSimple.end();
            int totalLength = value.length();

            if (totalLength <= 2) {
                val = totalLength == 1 ? value + m : value.charAt(0) + m;
            } else if (totalLength <= 6) {
                val = value.charAt(0) + String.join("", Collections.nCopies(totalLength - 2, m))
                        + value.substring(totalLength - 1);
            } else {
                int prefixLength = Math.min(start, totalLength - 1);
                int suffixLength = Math.min(end, totalLength - 1);

                if (prefixLength > totalLength) {
                    prefixLength = totalLength / 2;
                }
                if (suffixLength > totalLength) {
                    suffixLength = totalLength / 2;
                }

                int maskLength = Math.max(0, totalLength - (prefixLength + suffixLength));
                if (maskLength == 0) {
                    prefixLength -= 2;
                    suffixLength -= 2;
                    maskLength = Math.max(2, totalLength - (prefixLength + suffixLength));
                }

                prefixLength = Math.min(prefixLength, totalLength - 1);
                suffixLength = Math.min(suffixLength, totalLength - 1);

                maskLength = totalLength - prefixLength - suffixLength;

                val = value.substring(0, prefixLength) + String.join("", Collections.nCopies(maskLength, m))
                        + value.substring(totalLength - suffixLength);
            }
        }
        gen.writeString(val);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        sensitiveSimple = beanProperty.getAnnotation(SensitiveSimple.class);
        return this;
    }
}
